package com.ld.poetry.controller;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ld.poetry.aop.LoginCheck;
import com.ld.poetry.config.PoetryResult;
import com.ld.poetry.constants.CommonConst;
import com.ld.poetry.entity.Resource;
import com.ld.poetry.enums.PoetryEnum;
import com.ld.poetry.service.ResourceService;
import com.ld.poetry.utils.storage.StoreService;
import com.ld.poetry.utils.*;
import com.ld.poetry.utils.storage.FileStorageService;
import com.ld.poetry.vo.BaseRequestVO;
import com.ld.poetry.vo.FileVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源信息 前端控制器
 * </p>
 *
 * @author sara
 * @since 2022-03-06
 */
@RestController
@RequestMapping("/resource")
public class ResourceController {

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 保存资源信息
     * 
     * 功能说明：
     * 1. 保存新的资源信息到数据库
     * 2. 需要用户登录权限
     * 3. 记录资源的基本信息和上传者
     * 
     * 请求参数：
     * @param resource 资源信息对象，包含以下字段：
     *   - type: 资源类型（必填）
     *   - path: 资源路径（必填）
     *   - size: 资源大小（可选）
     *   - originalName: 原始文件名（可选）
     *   - mimeType: MIME类型（可选）
     *   - storeType: 存储类型（可选）
     * 
     * 返回结果：
     * @return PoetryResult 操作结果
     *   - 成功：返回成功信息
     *   - 失败：返回错误信息（如：信息不全）
     * 
     * 处理流程：
     * 1. 验证必填字段是否完整
     * 2. 创建新的资源对象
     * 3. 设置资源属性：
     *    - 复制传入的资源信息
     *    - 设置上传用户ID
     * 4. 保存到数据库
     * 
     * 注意事项：
     * 1. 需要用户登录才能操作
     * 2. 资源类型和路径为必填字段
     * 3. 其他字段为可选字段
     * 4. 通过userId字段记录上传者
     */
    @PostMapping("/saveResource")
    @LoginCheck
    public PoetryResult saveResource(@RequestBody Resource resource) {
        // 验证必填字段是否完整
        if (!StringUtils.hasText(resource.getType()) || !StringUtils.hasText(resource.getPath())) {
            return PoetryResult.fail("资源类型和资源路径不能为空！");
        }

        // 创建新的资源对象
        Resource re = new Resource();
        
        // 设置资源属性
        re.setPath(resource.getPath());           // 设置资源路径
        re.setType(resource.getType());           // 设置资源类型
        re.setSize(resource.getSize());           // 设置资源大小
        re.setOriginalName(resource.getOriginalName());  // 设置原始文件名
        re.setMimeType(resource.getMimeType());   // 设置MIME类型
        re.setStoreType(resource.getStoreType()); // 设置存储类型
        re.setUserId(PoetryUtil.getUserId());     // 设置上传用户ID

        // 保存到数据库
        resourceService.save(re);
        return PoetryResult.success();
    }

    /**
     * 上传文件
     * 
     * 功能说明：
     * 1. 上传文件到指定的存储平台
     * 2. 需要用户登录权限
     * 3. 保存文件信息到数据库
     * 
     * 请求参数：
     * @param file 上传的文件（必填）
     * @param fileVO 文件信息对象，包含以下字段：
     *   - type: 资源类型（必填）
     *   - relativePath: 相对路径（必填）
     *   - storeType: 存储类型（可选）
     *   - originalName: 原始文件名（可选）
     * 
     * 返回结果：
     * @return PoetryResult<String> 操作结果
     *   - 成功：返回文件访问路径
     *   - 失败：返回错误信息（如：文件为空、信息不全）
     * 
     * 处理流程：
     * 1. 验证必填字段是否完整
     * 2. 获取存储服务
     * 3. 保存文件到存储平台
     * 4. 创建资源记录
     * 5. 保存资源信息到数据库
     * 
     * 注意事项：
     * 1. 需要用户登录才能操作
     * 2. 文件和资源类型、相对路径为必填字段
     * 3. 文件大小会自动计算
     * 4. MIME类型会自动获取
     * 5. 通过userId字段记录上传者
     */
    @PostMapping("/upload")
    @LoginCheck
    public PoetryResult<String> upload(@RequestParam("file") MultipartFile file, FileVO fileVO) {
        System.out.println("fileVO");
        System.out.println(fileVO);
        // 验证必填字段是否完整
        if (file == null || !StringUtils.hasText(fileVO.getType()) || !StringUtils.hasText(fileVO.getRelativePath())) {
            return PoetryResult.fail("文件和资源类型和资源路径不能为空！");
        }

        // 设置文件到fileVO对象
        fileVO.setFile(file);
        
        // 获取存储服务
        StoreService storeService = fileStorageService.getFileStorage(fileVO.getStoreType());
        
        // 保存文件到存储平台
        FileVO result = storeService.saveFile(fileVO);

        // 创建资源记录
        Resource re = new Resource();
        
        // 设置资源属性
        re.setPath(result.getVisitPath());        // 设置访问路径
        re.setType(fileVO.getType());             // 设置资源类型
        re.setSize(Integer.valueOf(Long.toString(file.getSize())));  // 设置文件大小
        re.setMimeType(file.getContentType());    // 设置MIME类型
        re.setStoreType(fileVO.getStoreType());   // 设置存储类型
        re.setOriginalName(fileVO.getOriginalName());  // 设置原始文件名
        re.setUserId(PoetryUtil.getUserId());     // 设置上传用户ID

        // 保存资源信息到数据库
        resourceService.save(re);
        
        // 返回文件访问路径
        return PoetryResult.success(result.getVisitPath());
    }

    /**
     * 删除资源文件
     * 
     * 功能说明：
     * 1. 根据文件路径删除资源文件
     * 2. 需要管理员权限（@LoginCheck(0)）
     * 3. 同时删除数据库记录和存储系统中的文件
     * 
     * 请求参数：
     * @param path 文件路径（必填）
     * 这个 path 参数实际上就是 Resource 表中的 path 字段
     * 在文件上传时，我们存储的是 visitPath（访问路径）
     * 这个路径是相对于存储根目录的路径
     * 
     * 返回结果：
     * @return PoetryResult 操作结果
     *   - 成功：返回成功信息
     *   - 失败：返回错误信息（如：文件不存在）
     * 
     * 处理流程：
     * 1. 根据文件路径查询资源信息
     * 2. 验证资源是否存在
     * 3. 获取对应的存储服务
     * 4. 删除存储系统中的文件
     * 5. 返回操作结果
     * 
     * 注意事项：
     * 1. 需要管理员权限才能操作
     * 2. 文件路径必须存在
     * 3. 会同时删除数据库记录和存储系统中的文件
     */
    @PostMapping("/deleteResource")
    @LoginCheck(0)
    public PoetryResult deleteResource(@RequestParam("path") String path) {
        // 根据文件路径查询资源信息，只查询存储类型字段
        Resource resource = resourceService.lambdaQuery()
                .select(Resource::getStoreType)
                .eq(Resource::getPath, path)
                .one();
        
        // 验证资源是否存在
        if (resource == null) {
            return PoetryResult.fail("文件不存在：" + path);
        }

        // 获取对应的存储服务
        StoreService storeService = fileStorageService.getFileStorageByStoreType(resource.getStoreType());
        
        // 删除存储系统中的文件
        storeService.deleteFile(Collections.singletonList(path));
        
        return PoetryResult.success();
    }

    /**
     * 查询表情包列表
     * 
     * 功能说明：
     * 1. 获取管理员上传的表情包列表
     * 2. 需要用户登录权限
     * 3. 只返回已启用的表情包
     * 
     * 请求参数：
     * 无
     * 
     * 返回结果：
     * @return PoetryResult<List<String>> 操作结果
     *   - 成功：返回表情包路径列表
     *   - 失败：返回错误信息
     * 
     * 处理流程：
     * 1. 查询条件：
     *    - 资源类型为表情包（PATH_TYPE_INTERNET_MEME）
     *    - 状态为启用（STATUS_ENABLE）
     *    - 上传者为管理员
     * 2. 按创建时间倒序排序
     * 3. 只查询路径字段
     * 4. 转换为路径列表返回
     * 
     * 注意事项：
     * 1. 需要用户登录才能操作
     * 2. 只返回管理员上传的表情包
     * 3. 只返回已启用的表情包
     * 4. 返回的是文件访问路径列表
     */
    @GetMapping("/getImageList")
    @LoginCheck
    public PoetryResult<List<String>> getImageList() {
        // 查询表情包列表，只查询路径字段
        List<Resource> list = resourceService.lambdaQuery()
                .select(Resource::getPath)  // 只查询路径字段
                .eq(Resource::getType, CommonConst.PATH_TYPE_INTERNET_MEME)  // 资源类型为表情包
                .eq(Resource::getStatus, PoetryEnum.STATUS_ENABLE.getCode())  // 状态为启用
                .eq(Resource::getUserId, PoetryUtil.getAdminUser().getId())  // 上传者为管理员
                .orderByDesc(Resource::getCreateTime)  // 按创建时间倒序排序
                .list();
        
        // 转换为路径列表
        List<String> paths = list.stream()
                .map(Resource::getPath)  // 提取路径
                .collect(Collectors.toList());
        
        return PoetryResult.success(paths);
    }

    /**
     * 分页查询资源列表
     * 
     * 功能说明：
     * 1. 根据资源类型分页查询资源列表
     * 2. 需要管理员权限（@LoginCheck(0)）
     * 3. 支持按资源类型筛选
     * 
     * 请求参数：
     * @param baseRequestVO 分页请求对象，包含以下字段：
     *   - current: 当前页码（必填）
     *   - size: 每页大小（必填）
     *   - resourceType: 资源类型（可选）
     * 
     * 返回结果：
     * @return PoetryResult<Page<Resource>> 操作结果
     *   - 成功：返回分页资源列表
     *   - 失败：返回错误信息
     * 
     * 处理流程：
     * 1. 构建查询条件：
     *    - 如果指定了资源类型，则按类型筛选
     * 2. 按创建时间倒序排序
     * 3. 执行分页查询
     * 4. 返回分页结果
     * 
     * 注意事项：
     * 1. 需要管理员权限才能操作
     * 2. 分页参数为必填
     * 3. 资源类型为可选参数
     * 4. 结果按创建时间倒序排序
     */
    @PostMapping("/listResource")
    @LoginCheck(0)
    public PoetryResult<Page<Resource>> listResource(@RequestBody BaseRequestVO baseRequestVO) {
        // 构建分页对象
        Page<Resource> page = new Page<>(baseRequestVO.getCurrent(), baseRequestVO.getSize());
        
        // 执行分页查询
        Page<Resource> result = resourceService.lambdaQuery()
                .eq(StringUtils.hasText(baseRequestVO.getResourceType()), 
                    Resource::getType, baseRequestVO.getResourceType())  // 按资源类型筛选
                .orderByDesc(Resource::getCreateTime)  // 按创建时间倒序排序
                .page(page);  // 执行分页查询
        
        return PoetryResult.success(result);
    }

    /**
     * 修改资源状态
     */
    @GetMapping("/changeResourceStatus")
    @LoginCheck(0)
    public PoetryResult changeResourceStatus(@RequestParam("id") Integer id, @RequestParam("flag") Boolean flag) {
        resourceService.lambdaUpdate().eq(Resource::getId, id).set(Resource::getStatus, flag).update();
        return PoetryResult.success();
    }
}

